programming4us
           
 
 
Programming

iPhone Programming : Other View Controllers - Utility Applications

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
6/4/2011 4:36:46 PM
Utility applications perform simple tasks: they have a one-page main view and another window that is brought into view with a flip animation. The Stocks and Weather applications that ship with the iPhone and iPod touch are examples of applications that use this pattern. Both are optimized for simple tasks that require the absolute minimum of user interaction. Such applications are usually designed to display a simple list in the main view, with preferences and option settings on the flip view. You access the flip view by clicking a small i icon from the main view.

The Xcode Utility Application template implements the main view and gives the user access to a flipside view. It is one of the most extensive templates in Xcode and it implements a fully working utility application, which is fortunate as the documentation Apple provides regarding this type of application is otherwise somewhat lacking in details.

Open Xcode and start a new project. Click Application under the iPhone OS group, and then select Utility Application from the New Project window as the template (see Figure 1). Click Choose, and name the project “BatteryMonitor” when requested.

Figure 1. Selecting Utility Application in the New Project window


Figure 2 shows the Project window in Xcode and lists the files the template generates. The names of the classes the template generates are meant to hint strongly at what each of them does, but if not, Xcode has conveniently put the relevant classes into groups. Since the template implements all the logic necessary to control the application’s interface, we only need to implement our own UI and some basic logic to control it.

Click Build and Run to compile and run the application. You’ll find that it’s a fully working utility application, although with blank main and flipside views.

Figure 2. The new Utility Application project open in Xcode


1. Making the Battery Monitoring Application

The somewhat descriptive name of the application has probably revealed its purpose already. We’re going to implement a simple battery monitoring application, and to do so I’m going to introduce you to the UIDevice class. This is a singleton class that provides information relating to your hardware device. From it you can obtain information about your device such as its unique ID, assigned name, device model, and operating system name and version. More importantly, you can also use the class to detect changes in the device’s characteristics such as physical orientation, and register for notifications about when these characteristics change.


Note:

A singleton class is restricted in some manner such that only one instance of the class can be created. This design pattern can be used to coordinate actions or information across your application. Although some argue that because use of singleton classes introduces global state into your application, and is therefore almost by definition a bad thing, I think that when it is used correctly the pattern can simplify your architecture considerably.


Information—and notifications—about the device battery state weren’t introduced until the 3.0 update of the SDK. Even now the implementation is somewhat coarse-grained (notifications regarding charge level changes occur in only 5% increments).


Warning:

The UIDevice class has several limitations, and some developers have resorted to the underlying IOKit framework to obtain more information about the device (e.g., better precision to your battery measurements). However, while Apple marked the IOKit as a public framework, no documentation or header files are associated with it.

If you use this framework and try to publish your application on the App Store, it is possible that Apple will reject it for using a private framework despite its apparent public status. In the official documentation, IOKit is described as “Contain[ing] interfaces used by the device. Do not include this framework directly.”


1.1. Building our interface

First we’re going to build our interface. Double-click on the MainView.xib file (located in the Resources group in the Groups & Files pane) to open it in Interface Builder. You’ll see that the default view that Xcode generated already has the Info button to switch between the main and flipside views. Not only is it there, but it’s connected to the template code, so it’s already working.

The UI will consist of just three UILabel elements, so drag and drop three labels from the Library (⌘-Shift-L, then choose Cocoa TouchInputs & Values) onto the Main View window, and position them roughly as shown in Figure 3.

Figure 3. The Main View NIB file being edited in Interface Builder


You can use the Attributes Inspector (⌘-1) to change the font size and color as I have done with my view. We’ll be setting the text of the labels from inside our code, but for now I’ve added placeholder text (“100%”, “State:”, and “Unknown”) using the Attributes tab so that I can position the labels more neatly and get a better idea of how my UI will look.

That’s all we’re going to do to the main view. Save the file and return to Xcode. Open the FlipsideView.xib file. You’ll see that this time the default view that Xcode generates already has a navigation bar and a Done button present and connected to the template code. You need to add a label (UILabel) and switch (UISwitch) to this interface, as shown in Figure 4.

Figure 4. The flipside view being edited in Interface Builder


Drag and drop the two elements from the Library window (⌘-Shift-L, then choose Cocoa TouchInputs & Values) into the Flipside View window and position them as shown in Figure 6-4. Set the text of the label to “Monitor Battery”, and using the Attributes pane of the Inspector window set the label text color to white. The default black text won’t show up well against the dark gray background of the view. That’s all that’s needed. Save the file in Interface Builder, and open the BatteryMonitorAppDelegate.h file in Xcode (it’s in the Application Delegate folder in the Groups & Files pane).

1.2. Writing the code

In the interface, we need to add a Boolean variable that stores the flag that indicates whether the app is currently monitoring the battery state. Add the following inside the @interface declaration:

BOOL monitorBattery;

We also need to make this a property. Add the following next to the existing @property declarations (but before the @end):

@property (nonatomic) BOOL monitorBattery;

This means that in the BatteryMonitorAppDelegate.m implementation file, we also need to synthesize the property to create the accessor methods. Open that file and add the following next to the existing @synthesize statements:

@synthesize monitorBattery;

By default, we’re going to make it so that the application starts with battery monitoring turned off, so in the applicationDidFinishLaunching: method we must set the flag to NO. Add the following to the top of the method:

self.monitorBattery = NO;

Next, open the FlipSideViewController.h interface file (you can find it in the Flipside View folder in the Groups & Files pane) and add the lines shown in bold:

@class BatteryMonitorAppDelegate;

@interface FlipsideViewController : UIViewController {
id <FlipsideViewControllerDelegate> delegate;
BatteryMonitorAppDelegate *appDelegate;
IBOutlet UISwitch *toggleSwitch;
}

In the FlipSideViewController.m implementation file, you first need to import the application delegate header file (using the @class forward declaration in the interface file does not remove the need to #import this header file). Add the following line to the top of FlipSideViewController.m:

#import "BatteryMonitorAppDelegate.h"

Next, make the changes shown in bold to the viewDidLoad: method:

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
self.title = @"Preferences";
appDelegate = (BatteryMonitorAppDelegate *)
[[UIApplication sharedApplication] delegate];

toggleSwitch.on = appDelegate.monitorBattery;

}

Now modify the done: method to save the status of the toggle switch back to the application delegate when you close the flipside view:

- (IBAction)done {
appDelegate.monitorBattery = toggleSwitch.on;
[self.delegate flipsideViewControllerDidFinish:self];
}

Finally, add the following code to the dealloc: method (this releases the toggleS⁠witch variable):

- (void)dealloc {
[toggleSwitch release];
[super dealloc];
}

The modifications we need to make to the main view controller are a bit more extensive than those we’ve made thus far. Open the MainViewController.h interface file in Xcode and make the changes shown in bold. You can find this file in the Main View folder of the Groups & Files pane.

#import "FlipsideViewController.h"

@class BatteryMonitorAppDelegate;


@interface MainViewController : UIViewController
<FlipsideViewControllerDelegate>
{
BatteryMonitorAppDelegate *appDelegate;
IBOutlet UILabel *levelLabel;

IBOutlet UILabel *stateLabel;
}

- (IBAction)showInfo;

- (void)batteryChanged:(NSNotification *)note;
- (NSString *)batteryLevel;
- (NSString *)batteryState:(UIDeviceBatteryState )batteryState;

@end

Save the interface file, and then open the MainViewController.m implementation file in Xcode. We declared a reference to the application delegate in the interface file, so now we need to import the relevant header file. Add this line at the top:

#import "BatteryMonitorAppDelegate.h"

We also need to grab a reference to the application delegate in the viewDidLoad: method. Uncomment the method (remove the lines that consist solely of /* and */ immediately before and after the method) and add the lines shown in bold:

- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (BatteryMonitorAppDelegate *)
[[UIApplication sharedApplication] delegate];

}

Next, we need to implement the viewWillAppear: method. At this point, you may be wondering what the difference is between this method and the previous viewDidLoad: method. The answer is that they’re called at different times: viewWillAppear: will be called each time the view becomes visible, while viewDidLoad: is called only when the view is first loaded. Because the changes we make to the preferences (on the flip side) affect the main view, we need to use viewWillAppear:, which is triggered each time we flip back from the preferences view to the main view. Add the following to MainViewController.m:

- (void)viewWillAppear:(BOOL)animated {
UIDevice *device = [UIDevice currentDevice];
device.batteryMonitoringEnabled = appDelegate.monitorBattery;

if (device.batteryMonitoringEnabled) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(batteryChanged:)
name:@"UIDeviceBatteryLevelDidChangeNotification" object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(batteryChanged:)
name:@"UIDeviceBatteryStateDidChangeNotification" object:nil];
} else {

[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"UIDeviceBatteryLevelDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"UIDeviceBatteryStateDidChangeNotification" object:nil];
}
levelLabel.text = [self batteryLevel];
stateLabel.text = [self batteryState:device.batteryState];

[super viewWillAppear:animated];

}

Since the object may be registered as an observer when we deallocate this view, we also need to make sure we remove ourselves as an observer of any notifications in the dealloc: method. Add the lines shown in bold to the dealloc: method:

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[levelLabel release];
[stateLabel release];
[super dealloc];
}

We also need to implement the batteryChanged: method; this method is called when our application is notified of a change in battery state. Here, all we’re doing is updating the text of our two labels when we receive a notification of a change. Add the following to MainViewController.m:

- (void)batteryChanged:(NSNotification *)note {
UIDevice *device = [UIDevice currentDevice];
levelLabel.text = [self batteryLevel];
stateLabel.text = [self batteryState:device.batteryState];
}

Finally, we need to implement those convenience methods. Add the following to MainViewController.m:

- (NSString *)batteryLevel {
UIDevice *device = [UIDevice currentDevice];

NSString *levelString = nil;
float level = device.batteryLevel;
if ( level == -1 ) {
levelString = @"---%";
} else {
int percent = (int) (level * 100);
levelString = [NSString stringWithFormat:@"%i%%", percent];
}
return levelString;
}

- (NSString *)batteryState:(UIDeviceBatteryState )batteryState {

NSString *state = nil;
switch (batteryState) {
case UIDeviceBatteryStateUnknown:
state = @"Unknown";
break;
case UIDeviceBatteryStateUnplugged:
state = @"Unplugged";
break;
case UIDeviceBatteryStateCharging:
state = @"Charging";
break;
case UIDeviceBatteryStateFull:
state = @"Full";
break;
default:
state = @"Undefined";
break;
}
return state;
}


We’re done in Xcode; let’s go back into Interface Builder to make all the necessary connections. Locate FlipsideView.xib under Resources in the Groups & Files pane and double-click it to open it in Xcode.

1.3. Wiring the application in Interface Builder

In the FlipsideView.xib file we need to make only one connection: between the toggleS⁠witch outlet and the UISwitch. To make the connection, click File’s Owner in the FlipsideView.xib window, and then drag the toggleSwitch outlet from the Connections Inspector (⌘-2) to the switch, as shown in Figure 5.

Figure 5. Connecting the toggleSwitch outlet to the UISwitch in the flipside view


Save the FlipsideView.xib file and open the MainView.xib file. This time we need to make two connections. Just as you did in FlipsideView.xib, select File’s Owner and use the Connections Inspector to make connections between the levelLabel and stateLabel outlets and their corresponding UILabel in the main view, as shown in Figure 6.

Figure 6. Connecting the two outlets in our code to the UILabels in the main view


At this point, we’re done. We’ve implemented everything we need to in code, and we’ve linked all of our outlets to our interface. Unfortunately, since this application makes use of the UIDevice battery monitoring API, and iPhone Simulator doesn’t have a battery, we’re going to have to test it directly on the device.

To deploy the application onto your device, you need to edit the Bundle Identifier inside the BatteryMonitor-Info.plist file to something appropriate, and you need to set the Code Signing Identity associated with the project in the Project Info window (although in most cases Xcode will select an appropriate signing identity automatically, if you have more than one developer profile installed this isn’t guaranteed).  Once this is done, change the Active SDK in the overview window to “iPhone Device” and click Build and Run. Xcode should compile and deploy the application onto your iPhone.

Click the Info button in the bottom-lefthand corner to switch to the flip side and enable battery monitoring in the preferences pane. Click the Done button and return to the main view. Both the battery level and the state should have changed. While the battery level only changes every 5%, you can get some immediate feedback by plugging and unplugging your device from your Mac. The state should change from “Full” or “Charging” (see Figure 7) to “Unplugged”.

Figure 7. The main view and the flipside view of the Battery Monitor application

Other -----------------
- iPhone Programming : Table-View-Based Applications - Adding a City View
- iPhone Programming : Table-View-Based Applications - Adding Navigation Controls to the Application
- iPad SDK : Popovers - Popover Preparations
- iPad SDK : Preparing Dudel for a New Tool (part 5) - Rendering Multiple Styles
- iPad SDK : Preparing Dudel for a New Tool (part 4) - Creating a New Drawable Class
- jQuery 1.3 : AJAX - Loading data on demand (part 3) - Loading an XML document
- jQuery 1.3 : AJAX - Loading data on demand (part 2) - Working with JavaScript objects
- jQuery 1.3 : AJAX - Loading data on demand (part 1) - Appending HTML
- Coding JavaScript for Mobile Browsers (part 13) - Zoom and rotate gestures
- Coding JavaScript for Mobile Browsers (part 12) - Swipe gesture
- Coding JavaScript for Mobile Browsers (part 11)
- Coding JavaScript for Mobile Browsers (part 10) - Event Handling
- iPad SDK : Preparing Dudel for a New Tool (part 3) - Creating the Text Tool
- iPad SDK : Preparing Dudel for a New Tool (part 2) - Implementing Changes to the Controller Class
- Coding JavaScript for Mobile Browsers (part 9) - Scripting Styles
- Coding JavaScript for Mobile Browsers (part 8) - DOM
- iPad SDK : Preparing Dudel for a New Tool (part 1) - Setting Up the GUI
- Coding JavaScript for Mobile Browsers (part 7)
- Coding JavaScript for Mobile Browsers (part 6)
- iPad SDK : The Structure of Core Text
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us